let wasmLoader = async function (config) {
	if (!config.el || typeof config.el != 'object') {
		// throw new Error('挂载元素不能为空')
		console.error("挂载元素不能为空")
		return
	}
	if(!config.routMode){
		config.routMode = 'history'
	}
	let canvas = document.createElement('canvas')
	canvas.id = 'qtcanvas'
	canvas.style.cssText = `
        width: 100%;
        height: 100%;
        outline: none;
        cursor:default
    `
	canvas.setAttribute('contenteditable', true)
	canvas.oncontextmenu = function (e) {
		e.preventDefault()
	}
	config.el.appendChild(canvas)
	config.canvas = canvas
  if (config.path === undefined) {
	  config.path = 'assets'
		config.basePath = 'assets'
	}
	if (config.path.length > 0 && !config.path.endsWith('/')) {
		config.path = config.path.concat('/')		
		config.basePath = config.path.slice()
	}

	let Module = {
		emscriptenProperties: [
			'Module',
			'initScene',
			'proj4',
			'Li',
			'SSmap',
			'globalViewer',
			'GlobalViewer',
			'viewer',
			'Native',
		], // 用于存储 emscripten 模块的全局属性
		destroy() {
			if (this.calledRun) {
				SSmap.forceExit && SSmap.forceExit() //删除地球资源
				window._emscripten_cancel_main_loop() // 取消主循环
				window._emscripten_resize_heap(0) // 重置堆大小无效？
				window._emscripten_force_exit(0) // 强制退出
			} else {
				this.destroyed = true // 标记为已销毁
			}

			// 在下一帧清除window对象新增的emscripten属性
			setTimeout(() => {
				this.emscriptenProperties.forEach((property) => {
					if (Object.prototype.hasOwnProperty.call(window, property)) {
						delete window[property]
					}
				})
				this.emscriptenProperties = []
			}, 1)
		},
	}
	window.SSmap = window.Module = Module // 暴露 Module 对象到全局作用域,wasm 模块依赖它

	loadEmscriptenModule('SSmap')

	const { fetch: originalFetch } = window;
	async function repeatFetch(...args)  {
			let [resource, config] = args;
      let response = await originalFetch(resource, config);
			return response;				
		};
	function fetchResource(filePath) {
		let fullPath = config.path + filePath
		let fullPathData = repeatFetch(fullPath)
			.then(function (response) {
				if (response.ok) {
					let isType = response.headers.get('content-type').includes('text/html')
					if (isType) {
						// console.error('loader请求引擎内容出现异常')
						config.path = '../' + config.path
						return fetchResource(filePath)
					} else {
						let url = response.url.split(config.basePath)[0]
						config.baseUrl = url
						return response
					}
				}else{
					config.path = '../' + config.path
					return fetchResource(filePath)
				}
			})
			.catch((error) => {
				// 处理错误
				config.path = '../' + config.path
				return fetchResource(filePath)
			})
		return fullPathData
	}

	async function fetchText(filePath) {
		return await fetchResource(filePath).then(function (response) {
			return response.text()
		})
	}

	function fetchThenCompileWasm(response) {
		return response.arrayBuffer().then(function (data) {
			return WebAssembly.compile(data)
		})
	}

	function fetchCompileWasm(filePath) {
		return fetchResource(filePath).then(function (response) {
			if (typeof WebAssembly.compileStreaming !== 'undefined') {
				return WebAssembly.compileStreaming(response).catch(function () {
					return fetchThenCompileWasm(response)
				})
			} else {
				return fetchThenCompileWasm(response)
			}
		})
	}

	async function loadEmscriptenModule(applicationName) {
		let msg = 'Error: '
		if (typeof WebAssembly === 'undefined') {
			msg += 'WebAssembly is not supported'
			printError(msg)
			return
		}
		if (!webGLSupported()) {
			msg += 'WebGL is not supported'
			printError(msg)
			return
		}

		let emscriptenModuleSource = await fetchText(applicationName + '.js')
		let wasmModule = await fetchCompileWasm(applicationName + '.wasm')

		//销毁后不编译wasm模块
		if (Module.destroyed) {
			return
		}
		// 获取加载资源前的 window 属性
		let beforeProperties = Object.keys(window)
		try {
			completeLoadEmscriptenModule(emscriptenModuleSource, wasmModule)
			// 获取加载资源后的 window 属性
			let afterProperties = Object.keys(window)
			//保存加载wasm模块后新增的属性
			afterProperties.forEach((property) => {
				if (!beforeProperties.includes(property)) {
					Module.emscriptenProperties.push(property)
				}
			})
		} catch (error) {
			msg += error.message
			printError(msg)
		}
	}

	function completeLoadEmscriptenModule(emscriptenModuleSource, wasmModule) {
		Module.instantiateWasm = function (imports, successCallback) {
			WebAssembly.instantiate(wasmModule, imports).then(function (instance) {
				successCallback(instance, wasmModule)
			})
			return {}
		}
		Module.locateFile =
			Module.locateFile ||
			function (filename) {			
				return config.path + filename
			}
		Module.print =
			Module.print ||
			function (text) {
				if (config.stdoutEnabled) console.log(text)
			}
		Module.printErr =
			Module.printErr ||
			function (text) {
				if (
					text.startsWith !== undefined &&
					text.startsWith('bad name in getProcAddress:')
				) {
					return
				}
				if (config.stderrEnabled) console.log(text)
			}

		Module.mainScriptUrlOrBlob = new Blob([emscriptenModuleSource], {
			type: 'text/javascript',
		})

		Module.onAbort = function () {
			Module.printErr('This application is Exited')
		}

		Module.quit = function () {
			Module.printErr('This application is Exited')
		}

		Module.qtCanvasElements = [config.canvas]
		setMonitorEvents(config.canvas)//鼠标监听 设置为 default
		self.eval(emscriptenModuleSource)
	}

	function printError(text) {
		let span = document.createElement('span')
		span.innerText = text
		span.style.cssText = `
            position: absolute;
            left: 50%;
            top: 2.5em;
            transform: translateX(-50%);
            display: flex;
            flex-direction: column;
            align-items: center;
            line-height: 1.5;
        `
		config.el.appendChild(span)
		console.error(text)
	}

	function webGLSupported() {
		// We expect that WebGL is supported if WebAssembly is; however
		// the GPU may be blacklisted.
		try {
			var canvas = document.createElement('canvas')
			return !!(
				window.WebGLRenderingContext &&
				(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'))
			)
		} catch (e) {
			return false
		}
	}

	//监听鼠标事件
	function setMonitorEvents(dom) {
		dom.addEventListener('mouseover', function (e) {
			let cursor = dom.style.cursor
			if (cursor.includes('resize') && cursor !== 'default') {
				dom.style.cursor = 'default'
			}
		})
	}

	let promise = await new Promise((revsole) => {
		window.initScene = function () {
			window.GlobalViewer.canvasEl = canvas			
			//baseUrl
			window.GlobalViewer.setBaseUrl(config.baseUrl)	
				  
			SSmap.FontManager.instance().readyPromise.then(() => {		
				revsole({SSmap, Module, GlobalViewer:window.GlobalViewer})
			})
		}
	})
	return promise
}

export default wasmLoader
